package editor.main;

import java.awt.Component;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;

import org.kabeja.ui.impl.DXFFileTransferHandler;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

import editor.dxf.DxfModel;
import editor.modelo.EditorFloor;
import editor.modelo.Floor;
import editor.modelo.JSONConverter;
import editor.modelo.LandMark;
import editor.modelo.ModelUtilities;
import editor.modelo.JSONConverter.Formato;
import editor.modelo.Space;

public class BuildingManager  implements TableModelListener{


	private File rootFolder;
	private JSONConverter jConverterFloors ;
	private FloorTableModel ftm;
	private JTable table;
	private ArrayList<Floor> jsonsFloor;
	private ArrayList<DxfModel> dxfsFloor;	
	
	public BuildingManager(){
		jConverterFloors  = new JSONConverter(EditorFloor.class);
		ftm = new FloorTableModel();
		ftm.addTableModelListener(this);
		dxfsFloor = new ArrayList<DxfModel>();
		table = new JTable(ftm);
	}
	
	/**
	 * Crea la estructura y los jsons a partir de los dxf existentes en
	 * el directorio
	 * @param carpeta
	 */
	public void crearEdificio(File carpeta){
		rootFolder = carpeta;
		jsonsFloor = new ArrayList<Floor>();
		String[] archivosDxf = carpeta.list(new FilenameFilter() {
			@Override
			public boolean accept(File dir, String name) {
				return name.endsWith(".dxf");
			}
		});
		for(String archivo: archivosDxf){
			DxfModel d = new DxfModel(archivo.split("\\.")[0], 200, 200, 0);
			d.setFile(rootFolder.getAbsolutePath()+"/"+d.getID()+".dxf");
			
			dxfsFloor.add(d);
			//String archioJson = archivo.split("\\.")[0]+".json";
			//File json = new File(rootFolder.getAbsoluteFile()+ "/"+ archioJson);
			EditorFloor f = new EditorFloor();
			f.setbuildingName(rootFolder.getName());
			f.setFloorName(archivo.split("\\.")[0]);
			jsonsFloor.add(f);
		}
		if(jsonsFloor.size()>0){
			ftm.setPisos(jsonsFloor);
		}
	}
	
	public void loadBuilding(File carpeta){
		System.out.println("Cargando edificio : " + carpeta.getAbsolutePath());
		ArrayList<DxfModel> aux;
		rootFolder = carpeta;
		//cargo todos los .json de la carpeta
		jsonsFloor = ModelUtilities.loadBuilding(rootFolder, jConverterFloors);
		aux = getModelsFromString(rootFolder.getAbsolutePath()+"/dxfs.config");
		
		dxfsFloor = new ArrayList<DxfModel>();
		for(Floor f: jsonsFloor){
			String n = f.getFloorName();
			for(DxfModel m: aux){ //los ordeno y les doy su archivo
				if(m.getID().equals(n)){
					m.setFile(rootFolder.getAbsolutePath()+"/"+m.getID()+".dxf");
					dxfsFloor.add(m);
					break;
				}
			}
		}
		if(jsonsFloor.size()>0){
			ftm.setPisos(jsonsFloor);
		}
	}
	public void generarEdificio() {
		guardarTodo();
		jsonsFloor = ModelUtilities.generateBuilding(rootFolder, jConverterFloors);
		if(jsonsFloor.size()>0){
			ftm.setPisos(jsonsFloor);
		}
		generarListaAulas();
		//guardarTodo();
		//ModelUtilities.lo
	}

	public void guardarActual() {
		EditorFloor piso = getSelectedFloor();
		guardarPiso(piso);
		this.saveToFile(rootFolder.getAbsolutePath()+"/dxfs.config", toJSONString(this.dxfsFloor));
	}
	
	public void guardarTodo() {
		for(Floor ed: jsonsFloor){
			guardarPiso((EditorFloor) ed);
		}
		this.saveToFile(rootFolder.getAbsolutePath()+"/dxfs.config", toJSONString(this.dxfsFloor));
	}
	
	private void guardarPiso(EditorFloor piso) {
		if (piso != null){
			piso.checkFormat();
			jConverterFloors.toJSONFile(piso,	
					"./" + piso.getCompleteFloorName()+".json");
		}
	}

	public EditorFloor getSelectedFloor() {
		if(table.getSelectedRow() >=0){
			return (EditorFloor) ftm.getFloor(table.getSelectedRow());
		}
		else 
			return null;
	}
	
	public List<EditorFloor> getVisibleFloors(){
		ArrayList<EditorFloor> l = new ArrayList<EditorFloor>();
		for (int i = 0 ; i < ftm.getRowCount(); i++){
			if((Boolean) ftm.getValueAt(i, 1)){ //si esta seleccionado
				l.add((EditorFloor) ftm.getFloor(i));
			}
		}
		return l;
	}
	

	public void tableChanged(TableModelEvent e) {
		if(ftm.getRowCount()== 0)return;
		int a = e.getFirstRow();
		if((Boolean) ftm.getValueAt(a, 1)){ //si esta seleccionado
			//editorMapa.addPisoVisible((EditorFloor) ftm.getFloor(a));
		} else
			//editorMapa.removePisoVisible((EditorFloor) ftm.getFloor(a));
		//editorMapa.repaint();
			;
	}
	public void agregarNuevoPiso() {
		/*if(rootFolder == null){
			JOptionPane.showMessageDialog(null, "Debe seleccionar un directorio de trabajo primero");
			return;
		}
		String s = JOptionPane.showInputDialog("Ingrese el nombre del piso");
		if(s == null) return;
		EditorFloor f = new EditorFloor();
		f.setbuildingName(rootFolder.getName());
		f.setFloorName(s);
		//editorMapa.setSelectedFloor(f);
		ftm.addPiso(f);*/
		JOptionPane.showMessageDialog(null, "Por el momento no se puede agregar un piso sin un dxf");
	}
	
	public DxfModel getSelectedDxf_() {
		if(table.getSelectedRow() >=0){
			DxfModel dxf = dxfsFloor.get(table.getSelectedRow());
			if (!dxf.isInitialized())
				dxf.initialize(); 
			return dxf; }
		return null;
	}
	
	public List<DxfModel> getSelectedDxfs(){
		ArrayList<DxfModel> l = new ArrayList<DxfModel>();
		for (int i = 0 ; i < ftm.getRowCount(); i++){
			if((Boolean) ftm.getValueAt(i, 2)){ //si esta seleccionado
				DxfModel dxf = dxfsFloor.get(i);
				if (!dxf.isInitialized())
					dxf.initialize(); 
				l.add(dxf);
			}
		}
		return l;
	}
	public Component getFloorsTable() {
		return table;
	}
	
	/*
	 * Este codigo esta copiado y pegado del JSonConverter.. habria que refactorizarlo
	 */
	private void saveToFile(String path, String json) {
		try {
			FileWriter writer = new FileWriter(path);
			writer.write(json);
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private ArrayList<DxfModel> getModelsFromString(String path){
		return toModel(readFromFile(new File(path)));
	}

	private String readFromFile(File archivo) {
		String s= "";
		try {
			BufferedReader br = new BufferedReader(
					new FileReader(archivo));
			while(br.ready()){
				s+= br.readLine();
			}
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return s;
	}


	public ArrayList<Floor> getFloors() {
		return 	jsonsFloor; 	
	}

		private String toJSONString(List<DxfModel> modelos){
			Gson gson = new GsonBuilder().setPrettyPrinting().create();
			return  gson.toJson(modelos);
		}
		
		private ArrayList<DxfModel> toModel(String json){
			Gson gson = new Gson();
			Type tipo = new TypeToken<ArrayList<DxfModel>>() {}.getType();
			ArrayList<DxfModel> obj = gson.fromJson(json, tipo);
			return obj;
		}


		public void generarListaAulas(){
			LinkedList<String> aulas = new LinkedList<String>();
			for (Floor f : jsonsFloor) { //genera lista de aulas
				for(Space sp: f.getEspacios()){
					aulas.add(sp.getId());
				}
				for(LandMark lm: f.getLandmarks()){
					aulas.add(lm.getName());
				}
			}
			ModelUtilities.saveSpaceList(aulas, rootFolder);
			
		}
		

}
